/**
 * 
 */
package com.xpec.c4.service.module;

import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/**
 * 同步訊號管理
 * 
 * @author Eric_Wang
 *
 */
public class SyncSignalManager {

	//////////////////////////////////////////////////////////////////////
	/**
	 * 同步訊號物件
	 * @author Eric_Wang
	 *
	 */
	public class SyncSignalObject {
		/**
		 * 同步Id
		 */
		public int signalId;
		
		/**
		 * 返回值
		 */
		public Object returnObject;
		
		/**
		 * true : 有正常回傳結果
		 * false : timeout等不到結果
		 * 若回傳結果, 在call notifySyncSignal回傳值時會設成true
		 * 是用來查看是否此request等到timeout了
		 */
		private Boolean hasResult = false;
		
		SyncSignalObject() {
			this.signalId = maxId.incrementAndGet();
			if (this.signalId == 0) {
				this.signalId = maxId.incrementAndGet();
			}
		}

		public Boolean getHasResult() {
			return hasResult;
		}		
	}
	//////////////////////////////////////////////////////////////////////
	
	private static final Log log = LogFactory.getLog(SyncSignalManager.class);
	
	/**
	 * 最大值累加，避免Id重複
	 */
	private static AtomicInteger maxId = new AtomicInteger(0);
	
	/**
	 * 使用中的同步訊號物件
	 */
	private Map<Integer, SyncSignalObject> syncSignalMap = new ConcurrentHashMap<Integer, SyncSignalObject>();
	
	/**
	 * 回收的同步訊號物件
	 */
	private Queue<SyncSignalObject> syncSignalPool = new ConcurrentLinkedQueue<SyncSignalObject>();
	
	
	
	/**
	 * 取得可用的同步訊號物件
	 * 
	 * @return
	 * 		同步訊號物件
	 */
	public synchronized SyncSignalObject getSyncSignal() {
		SyncSignalObject syncSignal = null;
		
		if (syncSignalPool.isEmpty() == false) {
			syncSignal = syncSignalPool.remove();
		}
		
		if (syncSignal == null) {
			syncSignal = new SyncSignalObject();
		}
		
		syncSignalMap.put(syncSignal.signalId, syncSignal);
		return syncSignal;
	}
	
	/**
	 * 釋放同步訊號物件
	 * 
	 * @param syncSignal 同步訊號物件
	 */
	public synchronized void releaseSyncSignal(SyncSignalObject syncSignal) {
		syncSignalMap.remove(syncSignal.signalId);
		syncSignalPool.add(syncSignal);
		syncSignal.returnObject = null;
		syncSignal.hasResult = false;
	}
	
	/**
	 * 執行緒等待同步訊號物件
	 * 
	 * @param syncSignal 同步訊號物件
	 */
	public void waitSyncSignal(SyncSignalObject syncSignal, Long timeout) {
		if (syncSignal != null) {
			try {
				synchronized (syncSignal) {
					if(timeout != null) {
						syncSignal.wait(timeout);
					} else {
						syncSignal.wait();
					}
				}
			}
			catch (InterruptedException e) {
				log.error("waitSyncSignal error!");
			}
		}
	}
	
	/**
	 * 激發同步訊號物件(激發等待中的執行緒)
	 * 
	 * @param signalId 同步Id
	 * @param returnObject 返回值
	 */
	public void notifySyncSignal(int signalId, Object returnObject) {
		SyncSignalObject syncSignal = syncSignalMap.get(signalId);
		if (syncSignal != null) {
			synchronized (syncSignal) {
				syncSignal.hasResult = true;
				syncSignal.returnObject = returnObject;
				syncSignal.notifyAll();
			}
		}
	}

	
}
